'''
这个文件是主要开发文件，涵盖了策略全部的四个接口
-on_event接收比赛状态变化的信息。
    参数event_type type表示事件类型；
    参数EventArgument表示该事件的参数，如果不含参数，则为NULL。
-get_team_info控制队名。
    修改返回值的字符串即可修改自己的队名
-get_instruction控制5个机器人的轮速(leftspeed,rightspeed)，以及最后的reset(1即表明需要reset)
    通过返回值来给机器人赋轮速
    比赛中的每拍被调用，需要策略指定轮速，相当于旧接口的Strategy。
    参数field为In/Out参数，存储当前赛场信息，并允许策略修改己方轮速。
    ！！！所有策略的开发应该在此模块
-get_placement控制5个机器人及球在需要摆位时的位置
    通过返回值来控制机器人和球的摆位。
    每次自动摆位时被调用，需要策略指定摆位信息。
    定位球类的摆位需要符合规则，否则会被重摆
'''
# 导入随机数模块
import random
# 导入元组和联合类型
from typing import Tuple, Union

# 导入numpy用于数学计算
import numpy as np
# 导入V5RPC中定义的所有类和函数
from V5RPC import *
# 导入数学计算模块
import math
# 导入机器人基础类
from baseRobot import *
# 导入全局变量
from GlobalVariable import *

baseRobots = []  # 定义我方机器人数组
oppRobots = []   # 定义对方机器人数组
data_loader = DataLoader()  # 创建数据加载器实例
race_state = -1  # 定位球状态，-1表示初始状态
race_state_trigger = -1  # 触发方，-1表示未定义
num_goalkepper = -1  # 对方守门员编号，1代表有守门员，其他值代表没有
penalty = 1  # 点球的决策树策略选择，目前有5种
flag_penalty = -1  # 如果为1则需要切换点球策略
defend_flag = 0  # 0为正常防守，1为点球防守

goal_time = 0  # 记录门球时间
time = 0  # 统计门球造犯规失败次数
goal = 1  # 门球的决策树，目前有3种策略
flag_goal = 0  # 如果为1则切换门球策略
last_race_state = -1  # 记录上一次比赛状态
last_race_state_trigger = -1  # 记录上一次触发方
guard_goal = 1  # 门球防守的决策树，防止被对方造犯规

# 记录上一帧的球位置预测
last_futuerballx = 0
last_futuerbally = 0
# 记录不同策略开始的帧号
tickBeginPenalty = 0
tickBeginGoalKick = 0
tickBeginPlaceKick = 0
# 记录上一帧球的位置
lastBallx = -110 + 37.5
lastBally = 0
# 存储球的位置历史，用于预测
BallPos = [Vector2(0, 0)] * 100000
resetHistoryRecord = False  # 是否重置历史记录
newMatch = False  # 是否是新比赛

# 事件回调函数，处理比赛事件
@unbox_event
def on_event(event_type: int, args: EventArguments):
    # 定义事件处理字典，根据事件类型执行对应的匿名函数
    event = {
        0: lambda: print(args.judge_result.reason),  # 打印判罚原因
        1: lambda: print("Match Start"),  # 比赛开始
        2: lambda: print("Match Stop"),  # 比赛停止
        3: lambda: print("First Half Start"),  # 上半场开始
        4: lambda: print("Second Half Start"),  # 下半场开始
        5: lambda: print("Overtime Start"),  # 加时赛开始
        6: lambda: print("Penalty Shootout Start"),  # 点球大战开始
        7: lambda: print("MatchShootOutStart"),  # 点球大战开始(另一表示)
        8: lambda: print("MatchBlockStart")  # 突破重围开始
    }
    global race_state_trigger
    global race_state
    if event_type == 0:  # 如果是判罚结果事件
        race_state = args.judge_result.type  # 更新比赛状态
        race_state_trigger = args.judge_result.offensive_team  # 更新触发方
        # 根据不同的判罚类型打印信息
        if race_state == JudgeResultEvent.ResultType.PlaceKick:
            print("Place Kick")  # 开球
        elif race_state == JudgeResultEvent.ResultType.PenaltyKick:
            print("Penalty Kick")  # 点球
        elif race_state == JudgeResultEvent.ResultType.GoalKick:
            print("Goal Kick")  # 门球
        elif (race_state == JudgeResultEvent.ResultType.FreeKickLeftBot
              or race_state == JudgeResultEvent.ResultType.FreeKickRightBot
              or race_state == JudgeResultEvent.ResultType.FreeKickLeftTop
              or race_state == JudgeResultEvent.ResultType.FreeKickRightTop):
            print("Free Kick")  # 自由球

        # 定义执行方信息打印
        actor = {
            Team.Self: lambda: print("By Self"),  # 我方执行
            Team.Opponent: lambda: print("By Opp"),  # 对方执行
            Team.Nobody: lambda: print("By Nobody"),  # 无人执行
        }
        actor[race_state_trigger]()  # 打印执行方信息
    elif event_type == 6:  # 如果是点球大战开始事件
        race_state = 7  # 设置比赛状态为点球大战

    event[event_type]()  # 执行对应的事件处理函数


# 获取队伍信息函数
@unbox_int
def get_team_info(server_version: int) -> str:
    # 版本信息字典
    version = {
        0: "V1.0",
        1: "V1.1"
    }
    print(f'server rpc version: {version.get(server_version, "V1.0")}')
    global newMatch
    newMatch = True  # 设置为新比赛
    return '闲鱼买家'  # 返回队伍名称

# 守门员策略函数
def goalkeeper(field):
    global football_now_y, football_now_x
    global futureBally, futureBallx
    global defend_flag  # 点球防守标志

    # 获取当前球的位置
    football_now_x = field.ball.position.x
    football_now_y = field.ball.position.y 

    # 计算球的速度
    ball_velocity_x = football_now_x - BallPos[GlobalVariable.tick - 1].x
    ball_velocity_y = football_now_y - BallPos[GlobalVariable.tick - 1].y
    
    # 根据球速计算预测因子
    prediction_factor = min(12, 8 + 4 * math.sqrt(ball_velocity_x**2 + ball_velocity_y**2) / 10)
    
    # 预测球的未来位置
    futureBallx = prediction_factor * football_now_x - (prediction_factor - 1) * BallPos[GlobalVariable.tick - 1].x
    futureBally = prediction_factor * football_now_y - (prediction_factor - 1) * BallPos[GlobalVariable.tick - 1].y

    # 计算球速用于自适应定位
    ball_speed = math.sqrt(ball_velocity_x**2 + ball_velocity_y**2)
    
    # 判断球是否朝我方球门移动
    moving_toward_goal = ball_velocity_x > 0.5 and football_now_x > 0
    
    # 根据球速和方向调整守门员位置限制
    goalie_y_limit = min(22, 18 + ball_speed/2) if moving_toward_goal else 18

    # 球在球门y轴范围内的守门员行为
    if np.fabs(futureBally) <= 25:  # 球在球门y轴范围内
        if futureBallx < 0:  # 球在对方半场
            # 调整守门员位置，限制在球门y轴范围内
            if football_now_y*0.8 + futureBally*0.2 >= goalie_y_limit:
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, goalie_y_limit)
            elif football_now_y*0.8 + futureBally*0.2 <= -goalie_y_limit:
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, -goalie_y_limit)
            else:
                # 更灵敏的守门员定位
                baseRobots[1].moveto(GlobalVariable.goalkepper_X, football_now_y*0.7 + futureBally*0.3)  
        else:  # 球在我方半场
            if defend_flag == 1:  # 点球防守模式(不主动出击)
                # 改进的点球防守定位
                goalie_x = GlobalVariable.goalkepper_X
                # 当球靠近时稍微前移
                if futureBallx > 100 and abs(futureBally) < 15:
                    goalie_x = min(GlobalVariable.goalkepper_X + 2, 109)
                baseRobots[1].moveto(goalie_x, futureBally)
            else:  # 正常防守模式
                if futureBallx <= 65:  # 球还未到球门区
                    # 根据球的y位置调整守门员位置
                    if futureBally >= goalie_y_limit:
                        baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, goalie_y_limit - 2)
                    elif futureBally <= -goalie_y_limit:
                        baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, -goalie_y_limit + 2)
                    else:
                        baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, futureBally)
                else:  # 球已经到球门区
                    # 检查是否有对方球员进入我方守门区
                    num_in_goal = 0  
                    for i in range(0, 5):
                        if oppRobots[i].get_pos().x > 20 and np.fabs(oppRobots[i].get_pos().y) < 25 and oppRobots[i].get_pos().x - football_now_x < 5:
                            num_in_goal = 1 + num_in_goal
                        
                    if num_in_goal != 0:  # 对方有球员进入守门区
                        # 更积极的球拦截
                        baseRobots[1].moveto(futureBallx - 1, futureBally)
                    else:
                        # 正常防守，限制在球门范围内
                        if futureBally >= goalie_y_limit:
                            baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, goalie_y_limit)
                        elif futureBally <= -goalie_y_limit:
                            baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, -goalie_y_limit)
                        else:
                            # 改进的球追踪，使用加权预测                     
                            baseRobots[1].moveto(GlobalVariable.goalkepper_X, futureBally*0.6 + football_now_y*0.4)                                      
    else:  # 球不在球门y轴范围
        # 根据球在场地的不同位置调整守门员策略
        if futureBallx <= 0:  # 球在对方半场
            # 根据球的y位置适当调整守门员位置
            if futureBally > 20:
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, min(18, futureBally * 0.4))             
            elif futureBally < -20:
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, max(-18, futureBally * 0.4)) 
            else:
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, futureBally * 0.4)   
        elif futureBallx <= 60:  # 球在中场
            # 球在中场时更居中的定位
            if futureBally >= 30:
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, 15)    
            elif futureBally <= -30:  
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, -15)
            else:  # 球门范围内
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, futureBally * 0.5)  
        elif futureBallx <= 95:  # 球接近我方半场
            # 根据球的y位置调整守门员位置
            if futureBally >= 20:
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, 18)    
            elif futureBally <= -20:  
                baseRobots[1].moveto_dis(GlobalVariable.goalkepper_X, -18)
            else:  # 球门范围内
                baseRobots[1].moveto(GlobalVariable.goalkepper_X, futureBally)                                                           
        else:  # 球非常接近我方球门
            # 对于近距离威胁更积极的球拦截
            if abs(futureBally) < 25 and futureBallx > 100:
                baseRobots[1].moveto(futureBallx - 1, futureBally)
            else:
                baseRobots[1].moveto(GlobalVariable.goalkepper_X, futureBally)

# 常规比赛策略函数
def strategy_common(field):
    # 最基本最常规情况下的执行策略
    global football_now_x, football_now_y

    # 获取当前球的位置
    football_now_x = field.ball.position.x
    football_now_y = field.ball.position.y    
    
    # 预测足球位置
    global futureBallx, futureBally
    # 使用当前位置和上一帧位置进行简单线性预测
    futureBallx = 8 * football_now_x - 7 * BallPos[GlobalVariable.tick - 1].x
    futureBally = 8 * football_now_y - 7 * BallPos[GlobalVariable.tick - 1].y

    # 角色分配：1号作为守门员，2号控场，0号主要进攻
    
    # 防守策略部分
    if football_now_x > 5:  # 球在我方半场或中场
        # 0号机器人(主攻手)的行为
        # 避免进入守门区
        if (futureBallx > 80 or np.fabs(futureBally) < 40) or (football_now_x > 80 or np.fabs(football_now_y) < 40):
            baseRobots[0].moveto_dis(65, futureBally*0.8)  # 保持在安全位置
        else:
            # 根据球和其他机器人位置决定是突破还是射门
            if futureBallx > baseRobots[1].get_pos().x:           
                baseRobots[0].breakthrough(football_now_x, football_now_y, futureBallx+1, futureBally)
            else:
                baseRobots[0].shoot(futureBallx, futureBally, 10)                            

        # 3号机器人的行为
        # 避免进入守门区
        if (futureBallx > 70.5 or np.fabs(futureBally) < 40) or (football_now_x > 70 or np.fabs(football_now_y) < 40):
            baseRobots[3].moveto_dis(60, -70)  # 保持在左侧安全位置
        else:
            # 避免阻挡0号主攻手
            if baseRobots[0].get_pos().x > football_now_x and football_now_x > baseRobots[3].get_pos().x:
                baseRobots[3].moveto(futureBallx, -futureBally)  # 避让
            else:
                # 根据球的位置决定是突破还是直接移动
                if football_now_x > baseRobots[3].get_pos().x:
                    baseRobots[3].breakthrough(football_now_x, football_now_y, futureBallx+1, futureBally) 
                else:
                    baseRobots[3].moveto(futureBallx, futureBally)                                                     

        # 4号(2号机器人索引)的行为
        # 避免进入守门区
        if (futureBallx > 70.5 or np.fabs(futureBally) < 40) or (football_now_x > 70 or np.fabs(football_now_y) < 40):
            baseRobots[2].moveto_dis(60, 70)  # 保持在右侧安全位置
        else:
            # 根据球的位置决定是突破还是直接移动
            if football_now_x > baseRobots[2].get_pos().x:
                baseRobots[2].breakthrough(football_now_x, football_now_y, futureBallx+1, futureBally) 
            else:
                baseRobots[2].moveto(futureBallx, futureBally)

        # 调用守门员策略
        goalkeeper(field)

        # 5号(4号机器人索引)中场后卫行为
        if futureBallx > baseRobots[4].get_pos().x:
            baseRobots[4].move_in_still_x(55, -futureBally)  # 保持在固定x位置拦截
        else:      
            # 保持在固定x位置拦截，同时根据球位置调整y
            baseRobots[4].move_in_still_x(55, football_now_y*0.8 + futureBally*0.2)
            # 计算与球的距离
            dx = football_now_x - baseRobots[4].get_pos().x
            dy = football_now_y - baseRobots[4].get_pos().y
            distance = math.sqrt(dx * dx + dy * dy)        
            # 当球非常接近时进行快速转向射球
            if distance < 2 and dx > 0:
                if football_now_y < 0:
                    baseRobots[4].set_wheel_velocity(125, -125)
                else:
                    baseRobots[4].set_wheel_velocity(-125, 125)

    # 进攻策略部分
    if football_now_x <= 5:  # 球在对方半场
        if futureBallx+1 > -75 + 3:  # 球还没到禁区
            # 0号主攻手射门，3号辅助
            baseRobots[0].shoot(futureBallx+1, futureBally, 10)
            baseRobots[3].move_with_angle(futureBallx+1, futureBally, 180)  # 4号自由人追球
        else:  # 球已进入对方禁区
            # 检查对方是否有守门员
            num_in_goal = 0
            for i in range(0, 5):
                if oppRobots[i].get_pos().x < -94 and np.fabs(oppRobots[i].get_pos().y) < 30:
                    num_in_goal += 1          

            if num_in_goal == 1:  # 有守门员
                # 计算0号机器人与球的距离
                distance1_ball = math.sqrt((football_now_x - baseRobots[0].get_pos().x) ** 2 + (football_now_y - baseRobots[0].get_pos().y) ** 2)
                # 如果在球门区且球在近前，根据位置决定行为
                if futureBallx < -80 and distance1_ball < 10:
                    if baseRobots[0].get_pos().x <= football_now_x:  # 0号在球的左侧                 
                         baseRobots[0].breakthrough(football_now_x, football_now_y, futureBallx+1, futureBally) 
                    else:  # 快速转向射球
                        if football_now_y < 0:
                            baseRobots[0].set_wheel_velocity(125, -125)
                        else:
                            baseRobots[0].set_wheel_velocity(-125, 125) 
                else:  # 调整位置
                    baseRobots[0].move_with_angle(futureBallx+1, futureBally, 180)
                    # 当球靠近对方球门时调整位置
                    if (futureBallx < -90 and np.fabs(futureBally) <= 60):
                        baseRobots[0].moveto_dis(-80, futureBally)

                # 3号机器人的辅助行为
                if baseRobots[3].get_pos().x <= football_now_x:  # 3号在球的左侧 
                    baseRobots[3].breakthrough(football_now_x, football_now_y, futureBallx+1, futureBally)
                else:
                    baseRobots[3].move_with_angle(futureBallx+1, futureBally, 180)
                
                # 计算3号机器人与预测球位置的距离
                distance3_ball = math.sqrt((futureBallx - baseRobots[3].get_pos().x) ** 2 + (futureBally - baseRobots[3].get_pos().y) ** 2)
                # 当接近球且在球后方时快速转向射球
                if (baseRobots[3].get_pos().x > futureBallx and distance3_ball < 10):
                    if football_now_y < 0:
                        baseRobots[3].set_wheel_velocity(125, -125)
                    else:
                        baseRobots[3].set_wheel_velocity(-125, 125) 
                # 当球靠近对方球门时调整位置
                if (futureBallx < -90 and np.fabs(futureBally) <= 50):
                    baseRobots[3].moveto_dis(-75, futureBally)             
            else:  # 没有守门员，直接射门
                baseRobots[0].shoot(futureBallx+1, futureBally, 10)

        # 中场后卫(5号，索引4)的行为
        # 计算与球的距离
        distance2_ball = math.sqrt((football_now_x - baseRobots[4].get_pos().x) ** 2 + (football_now_y - baseRobots[4].get_pos().y) ** 2)
        # 当球很近且在自己前方时射门
        if distance2_ball < 5 and (baseRobots[4].get_pos().x - football_now_x) > 0:
            if football_now_y < 0:
                baseRobots[4].set_wheel_velocity(125, -125)
            else:
                baseRobots[4].set_wheel_velocity(-125, 125)            
        else:  # 保持在固定x位置拦截
            baseRobots[4].move_in_still_x(45, football_now_y*0.8 + futureBally*0.2)
                        
        # 4号机器人(索引2)的行为
        # 计算与球的距离
        distance4_ball = math.sqrt((football_now_x - baseRobots[2].get_pos().x) ** 2 + (football_now_y - baseRobots[2].get_pos().y) ** 2)
        # 当球很近且在自己前方时射门
        if distance4_ball < 5 and (baseRobots[2].get_pos().x - football_now_x) > 0:
            if football_now_y < 0:
                baseRobots[2].set_wheel_velocity(125, -125)
            else:
                baseRobots[2].set_wheel_velocity(-125, 125)            
        else:  # 保持在固定x位置拦截
            baseRobots[2].move_in_still_x(0, futureBally)
            
        # 调用守门员策略
        goalkeeper(field)

# 点球策略函数
def strategy_penalty(field):
    # 获取当前球位置
    football_now_x = field.ball.position.x
    football_now_y = field.ball.position.y
    # 预测球的位置
    futureBallx = 8 * football_now_x - 7 * BallPos[GlobalVariable.tick - 1].x
    futureBally = 8 * football_now_y - 7 * BallPos[GlobalVariable.tick - 1].y
    
    global tickBeginPenalty, race_state_trigger, flag_penalty, penalty
    goalkeeper_num = 0
   
    if race_state_trigger == Team.Self:  # 我方主罚点球
        # 先将所有机器人停止
        for i in range(0, 5):
            baseRobots[i].set_wheel_velocity(0, 0)
            
        if penalty == 2:  # 点球策略1：守门员定点射门
            # 根据时间和位置控制机器人行为
            if GlobalVariable.tick - tickBeginPenalty <= 30:        
                if np.fabs(baseRobots[0].get_pos().x) < 64.5001:
                    baseRobots[0].set_wheel_velocity(-125, -125)
                else:
                    baseRobots[0].set_wheel_velocity(125, -125)
            else:  # 超过30帧未进球，切换策略
                flag_penalty = 1  # 30拍没进球就是点球没进，换策略
                strategy_common(field)
                
        elif penalty == 1:  # 点球策略2：守门员绕C字
            # 根据时间分段控制机器人行为
            if GlobalVariable.tick - tickBeginPenalty <= 8:
                baseRobots[0].set_wheel_velocity(-110, -77)
            elif GlobalVariable.tick - tickBeginPenalty <= 19:
                baseRobots[0].set_wheel_velocity(-90, -120)
            elif GlobalVariable.tick - tickBeginPenalty <= 28:
                baseRobots[0].set_wheel_velocity(-10, -125)
            elif GlobalVariable.tick - tickBeginPenalty <= 68:
                baseRobots[0].shoot(futureBallx, futureBally, 10)
            else:  # 超过68帧未进球，切换策略
                flag_penalty = 1
                strategy_common(field)
                
        elif penalty == 4:  # 3号战术：队友辅助射门
            if GlobalVariable.tick - tickBeginPenalty <= 65:
                # 3号机器人固定速度前进
                baseRobots[3].set_wheel_velocity(80, 80)
                # 根据4号机器人位置调整0号和4号行为
                if 8 > np.fabs(baseRobots[4].get_pos().x):
                    baseRobots[0].set_wheel_velocity(80, 80)
                    baseRobots[4].set_wheel_velocity(125, 125)
                elif 8 < np.fabs(baseRobots[4].get_pos().x) < 31:
                    baseRobots[4].set_wheel_velocity(105, 125)
                    if 12 < np.fabs(baseRobots[4].get_pos().x) < 31:
                        baseRobots[0].set_wheel_velocity(40,20)  
                elif  50 > np.fabs(baseRobots[4].get_pos().x) > 31:
                    baseRobots[0].set_wheel_velocity(65,45)
                    baseRobots[4].set_wheel_velocity(125,125)
                elif  np.fabs(baseRobots[4].get_pos().x) > 50:
                    baseRobots[4].set_wheel_velocity(125,-125)
            else:
                flag_penalty = 1 
                strategy_common(field)
        elif penalty == 3:    #4号战术，队友辅助射门
          if GlobalVariable.tick - tickBeginPenalty <= 55:
            if  10 > np.fabs(baseRobots[3].get_pos().x) :
                baseRobots[0].set_wheel_velocity(90, 90)
                baseRobots[3].set_wheel_velocity(125,125)
            elif 10 < np.fabs(baseRobots[3].get_pos().x) < 35:
                baseRobots[3].set_wheel_velocity(102.7, 125)
                if 12 < np.fabs(baseRobots[3].get_pos().x) < 35:
                    baseRobots[0].set_wheel_velocity(40,20)  
            elif 60 > np.fabs(baseRobots[3].get_pos().x) > 35:
                baseRobots[0].set_wheel_velocity(65,45)
                baseRobots[3].set_wheel_velocity(125,125)
          else:
                flag_penalty = 1 
                strategy_common(field)
        elif penalty == 5:    #点球策略5： 简易c字                                  
          if GlobalVariable.tick - tickBeginPenalty <=55:
             if  np.fabs(baseRobots[0].get_pos().x) < 69:
                baseRobots[0].set_wheel_velocity(91,95)
             elif  74 > np.fabs(baseRobots[0].get_pos().x) > 69:
                baseRobots[0].set_wheel_velocity(60,95)
             elif  np.fabs(baseRobots[0].get_pos().x) > 74:
                baseRobots[0].set_wheel_velocity(125,-125)
          else:
                flag_penalty = 1 
                strategy_common(field)
          
    if race_state_trigger == Team.Opponent:
        if GlobalVariable.tick - tickBeginPenalty <= 60 :
            baseRobots[0].moveto_dis(50, -15)
            baseRobots[2].moveto_dis(50, 15)
            baseRobots[3].moveto_dis(70, -65)
            baseRobots[4].moveto_dis(70, 65)
            goalkeeper (field)
        else:
            strategy_common(field) 

def strategy_goalkick(field):  #门球策略
    global tickBeginGoalKick
    global race_state_trigger
    global goal,guard_goal

    football_now_x = field.ball.position.x
    football_now_y = field.ball.position.y
    # 预测足球位置
    futureBallx = 8 * football_now_x - 7 * BallPos[GlobalVariable.tick - 1].x
    futureBally = 8 * football_now_y - 7 * BallPos[GlobalVariable.tick - 1].y       

    if race_state_trigger == Team.Self:
        if goal == 1:  #造犯规策略
            for i in range(2, 5):
                baseRobots[i].set_wheel_velocity(125, -125)
            baseRobots[0].moveto_dis(-50, 30)              
            baseRobots[1].set_wheel_velocity(0, 0)  #守门员 
        
        elif goal == 2:  #正常策略
            if GlobalVariable.tick - tickBeginGoalKick <= 75:
                for i in range(0, 5):
                    baseRobots[i].set_wheel_velocity(0, 0)
                baseRobots[1].set_wheel_velocity(125, 125)
            else:
                strategy_common(field)
        elif goal == 3: #开球直踢型策略
            for i in range(0, 5):
                baseRobots[i].set_wheel_velocity(0, 0)
            if GlobalVariable.tick - tickBeginGoalKick <= 30:
                 baseRobots[1].set_wheel_velocity(125, 125) 
            elif GlobalVariable.tick - tickBeginGoalKick <= 45:
                 baseRobots[1].set_wheel_velocity(125, -125)                  
            else:
                 strategy_common(field)            

    if race_state_trigger == Team.Opponent:
        if guard_goal == 1:
            if GlobalVariable.tick - tickBeginGoalKick <= 80:
                baseRobots[0].shoot (futureBallx,futureBally,10)               
                baseRobots[2].move_in_still_x  (65,futureBally)  #2号后卫起一个拦截作用
                baseRobots[3].moveto(25, futureBally) 
                baseRobots[4].moveto(50, futureBally)
                goalkeeper (field)               
            else:               
                strategy_common(field)
        elif guard_goal == 2:  #防止被对方造犯规
            goalkeeper (field)
            distance1_ball = math.sqrt((football_now_x - baseRobots[0].get_pos().x) ** 2 + (football_now_y - baseRobots[0].get_pos().y) ** 2)
            if futureBallx < -80 and distance1_ball < 10:  #在球门区而且球在跟前
                if baseRobots[0].get_pos ().x <= football_now_x and np.fabs(baseRobots[0].get_pos ().x-football_now_y)<1:  #0号在球的左侧                 
                    baseRobots[0].breakthrough (football_now_x,football_now_y,futureBallx+1,futureBally)  
                else :
                    if football_now_y < 0:
                        baseRobots[0].set_wheel_velocity(125, -125)
                    else:
                        baseRobots[0].set_wheel_velocity(-125, 125) 
            else :
                baseRobots[0].shoot (futureBallx,futureBally,10)
                if (futureBallx<-95 and np.fabs(futureBally)<25):
                    baseRobots[0].moveto_dis (-80,futureBally) 
            baseRobots[2].move_in_still_x  (65,futureBally*0.9)  #2号后卫起一个拦截作用
            baseRobots[3].moveto(25, football_now_y) 
            baseRobots[4].moveto(50, football_now_y)                                                  

def strategy_PlaceKick (field): #开球策略
    global tickBeginPlaceKick
    global race_state_trigger
    

    football_now_x = field.ball.position.x
    football_now_y = field.ball.position.y
    # 预测足球位置
    futureBallx = 8 * football_now_x - 7 * BallPos[GlobalVariable.tick - 1].x
    futureBally = 8 * football_now_y - 7 * BallPos[GlobalVariable.tick - 1].y 
    futureBally2 = 9 * football_now_y - 8 * BallPos[GlobalVariable.tick - 1].y


    if race_state_trigger == Team.Self:
        for i in range(2, 5):
            baseRobots[i].set_wheel_velocity(0, 0)
            if GlobalVariable.tick - tickBeginPlaceKick <= 100:
                if GlobalVariable.tick - tickBeginPlaceKick <= 27:
                    baseRobots[0].set_wheel_velocity (125,125)
                    baseRobots[3].set_wheel_velocity (125,125)
                    goalkeeper (field) 
                else:
                    strategy_common(field)                    
            else:
                    strategy_common(field)
    if race_state_trigger == Team.Opponent:
            if GlobalVariable.tick - tickBeginPlaceKick <= 135:
                strategy_common(field)      

                if futureBally > 35 :
                    baseRobots[4].moveto_dis(79,8)     
                elif futureBally < -35  :
                    baseRobots[4].moveto_dis(79,-8)  
                else:
                    baseRobots[4].moveto_dis(79,futureBally2)

                if  futureBallx > 55:
                    baseRobots[2].moveto (55,futureBally)                 
                    baseRobots[3].moveto (60,futureBally) 
                elif futureBallx < -65:
                    baseRobots[2].moveto (-60,futureBally)                 
                    baseRobots[3].moveto (-65,futureBally) 
                else:
                     if futureBallx < 0 :
                        baseRobots[2].moveto (futureBallx*1.8,30)                 
                        baseRobots[3].moveto (futureBallx*1.8,-30)  
                     else:
                        baseRobots[2].moveto (futureBallx,30)                 
                        baseRobots[3].moveto (futureBallx,-30)                         

            else:            
                strategy_common(field)


@unbox_field
def get_instruction(field: Field):  #策略接口
    # python start.py 20000    print(field.tick)  # tick从2起始
    GlobalVariable.tick = field.tick
    global resetHistoryRecord

    for i in range(0, 5): # 0 1 2 3 4
        baseRobots.append(BaseRobot()) 
        oppRobots.append(BaseRobot())
        baseRobots[i].update(field.self_robots[i], resetHistoryRecord)
        oppRobots[i].update(field.opponent_robots[i], resetHistoryRecord)
        global newMatch
        if field.tick == 2: #newMatch is True:
            for j in range(0, 8):
                baseRobots[i].HistoryInformation[j] = field.self_robots[i].copy()   # 第0拍主动维护历史数据
                baseRobots[i].PredictInformation[j] = field.self_robots[i].copy()	# 第0拍主动维护预测数据
            newMatch = False
        baseRobots[i].PredictRobotInformation(GlobalVariable.tick_delay)#(GlobalVariable.tick_delay)

    football_now_x = field.ball.position.x   # 蓝方假设
    football_now_y = field.ball.position.y

    field.ball.position.x = field.ball.position.x
    field.ball.position.y = field.ball.position.y

    global BallPos
    BallPos[GlobalVariable.tick] = Vector2(football_now_x, football_now_y)
    if resetHistoryRecord is True:
        for i in range(GlobalVariable.tick, GlobalVariable.tick - 11, -1):
            BallPos[i] = Vector2(football_now_x, football_now_y)
    #print (race_state)
    #根据情况执行什么样的策略
    if race_state == JudgeResultEvent.ResultType.PenaltyKick:
        strategy_penalty(field)  #点球策略 2
    elif race_state == JudgeResultEvent.ResultType.GoalKick:
        strategy_goalkick(field) #门球策略 1
    elif race_state == JudgeResultEvent.ResultType.PlaceKick:
        strategy_PlaceKick (field) #开球策略0
    else :
        strategy_common(field)


    for i in range(0, 5):
        baseRobots[i].save_last_information(football_now_x, football_now_y)
    data_loader.set_tick_state(GlobalVariable.tick, race_state)
    resetHistoryRecord = False

    velocity_to_set = []
    for i in range(0, 5):
        velocity_to_set.append((baseRobots[i].robot.wheel.left_speed, baseRobots[i].robot.wheel.right_speed))

    return velocity_to_set, 0    # 以第二元素的(0,1)表明重置开关,1表示重置


@unbox_field
def get_placement(field: Field) -> List[Tuple[float, float, float]]:  #返回摆球时的坐标 接口
    final_set_pos: List[Union[Tuple[int, int, int], Tuple[float, float, float]]]
    global resetHistoryRecord
    resetHistoryRecord = True
    global flag_penalty,penalty
    global flag_goal,goal
    global last_race_state,last_race_state_trigger
    global guard_goal
    global defend_flag,time

    defend_flag = 0
    global goal_time

    '点球决策树'
    if  flag_penalty == 1 :
        penalty = penalty + 1
        if penalty > 5:
            penalty = 1
    flag_penalty = -1
    '点球决策树'

    '门球决策树'
    if flag_goal == 1:  #进入门球摆位了置1
        #1.造犯规成功了继续造犯规策略  2.对方连续犯了5次
        if last_race_state == race_state or (race_state == JudgeResultEvent.ResultType.PlaceKick and race_state_trigger != Team.Self and goal_time>=3): 
            goal = 1
            goal_time = goal_time + 1
            if goal_time>=3:
                goal_time = 0
        #1.对方不犯规  2.其他没有造成功的情况
        else:    #两种点球策略谁进球了就继续
            if race_state == JudgeResultEvent.ResultType.PlaceKick and race_state_trigger != Team.Self: #上一种门球进球了
                # goal = goal'
                flag_goal = 0
            else:
                goal = goal+1
                if goal >= 4:
                    if time >= 3:
                        goal = 2
                    else:
                        goal = 1
                time = time + 1

    flag_goal = 0

    #连续两次次触发对方门球 则说明对方在造犯规
    if (last_race_state == 1 and race_state == 1) and (last_race_state_trigger != Team.Self and race_state != Team.Self):
            guard_goal = 2
    else :
            guard_goal = 1

    '门球决策树'    

    if race_state == JudgeResultEvent.ResultType.PlaceKick:
        global tickBeginPlaceKick
        tickBeginPlaceKick = field.tick       
        if race_state_trigger == Team.Self:
            print("开球进攻摆位")
            set_pos = [
                [-7 ,-7.5, 55],   
                [GlobalVariable.goalkepper_X, 0, 90],#守门员             
                [5, 32, 180],
                [55.8, 61.5, -130],
                [50, 0, 180],       
                [0.0, 0.0, 0.0]]
            # set_pos = [(-103, 0, 90), (30, 0, 0), (-3, -10, 0), (-3, 10, 0), (-3, 0, 0), (0.0, 0.0, 0.0)]
        else:   # if race_state_trigger == Team.Opponent:
            print("开球防守摆位")
            set_pos = [            
                [30, 0, 180],
                [GlobalVariable.goalkepper_X, 0, 90],                           
                [7, 30, 180],
                [7, -30, 180],
                [79, 0, 180],
                [0.0, 0.0, 0.0]]
            # set_pos = [(-105, 0, 90), (10, 20, -90), (10, -20, -90), (10, 40, -90), (10, -40, -90), (0.0, 0.0, 0.0)]
    elif race_state == JudgeResultEvent.ResultType.PenaltyKick:
        global tickBeginPenalty
        tickBeginPenalty = field.tick
        if race_state_trigger == Team.Self:
            print("点球进攻摆位")
            if penalty == 2:#直接射门策略摆位
                set_pos = [
                       [-64.5,6,35],
                       [GlobalVariable.goalkepper_X, 0, 90],
                       [0, 50, 180],
                       [10, -50, 160],
                       [0, 0, -180],
                       [-5, -10, 0.0]]
            elif penalty == 1:   #复杂c字种策略摆位         
                set_pos = [
                         [-64, -1.2, -8.6],
                         [GlobalVariable.goalkepper_X, 0, 90],
                        [10, -70, 14],
                        [10, 60, -30],
                        [10, -60, 14],
                        [-5, 10, 0.0]]
            elif penalty == 4:#队友辅助射门策略摆位
                set_pos = [
                       [-76.5, -9, 70],
                       [GlobalVariable.goalkepper_X, 0, 90],
                       [5, 55, -180],
                       [5, 75, -165],
                       [5, 85,-165],
                       [-5, -10, 0.0]]     
            elif penalty == 3:#队友辅助射门策略摆位
                set_pos = [
                      [-76.5, -9, 70],
                      [GlobalVariable.goalkepper_X, 0, 90],
                       [0, 50, 180],
                       [5, 60,-170],
                       [0, 0, -180],
                       [-5, -10, 0.0]]     
            elif penalty == 5:#简易c字策略摆位
                set_pos = [
                       [-67.5, -8, 90],
                       [GlobalVariable.goalkepper_X, 0, 90],
                       [0, 50, 180],
                       [10, -50, 160],
                       [0, 0, -180],
                       [-5, -10, 0.0]]    
            
        else:   # if race_state_trigger == Team.Opponent:
            defend_flag = 1
            print("点球防守摆位")
            set_pos = [
                       [-10, 50,-40],
                       [GlobalVariable.goalkepper_X, 0, 180],
                       [-10, -40,40],
                       [-7, -65,-15],
                       [-7, 65, 15],
                       [0, 0.0, 0.0]]
    elif race_state == JudgeResultEvent.ResultType.GoalKick:
        global tickBeginGoalKick
        tickBeginGoalKick = field.tick
        if race_state_trigger == Team.Self:
            flag_goal = 1

            print("门球进攻摆位")
            if goal == 1:
                set_pos = [
                        [5, 85, -90],
                        [100, 9.05, 90],
                        [5, -85, 90],
                        [30, 85, -90],
                        [30, -85, 90],
                        [105, 9.05, 0.0]]
            elif goal == 2:
                set_pos = [
                        [50, -20, 90],
                        [102, 5.05, 90],
                        [50, -40, 90],
                        [30, 0, 90],
                        [50, 0, 90],
                        [104.5, 9.05, 0.0]] 
            elif goal == 3:
                 set_pos = [
                        [5, 85, 90],
                        [106, -4, 180],
                        [5, -80, 90],
                        [30, 80, 90],
                        [30, -80, 90],
                        [98, -4, 0.0]]                                
        else:   # if race_state_trigger == Team.Opponent:
            print("门球防守摆位")
            set_pos = [
                       [5, 0, 180],
                       [GlobalVariable.goalkepper_X, 0, 90],
                       [65, -40, 180],
                       [25, 40, 180],
                       [50, 0, 180],
                       [0.0, 0.0, 0.0]]
    elif (race_state == JudgeResultEvent.ResultType.FreeKickLeftTop
          or race_state == JudgeResultEvent.ResultType.FreeKickRightTop
          or race_state == JudgeResultEvent.ResultType.FreeKickRightBot
          or race_state == JudgeResultEvent.ResultType.FreeKickLeftBot):
        if race_state_trigger == Team.Self:
            print("争球进攻摆位")
            set_pos = [
                       [30, 0, 0],
                       [GlobalVariable.goalkepper_X, 0, 90],
                       [-3, -10, 0],
                       [-3, 10, 0],
                       [-3, 0, 0],
                       [0.0, 0.0, 0.0]]
        else:   # if race_state_trigger == Team.Opponent:
            print("争球防守摆位")
            set_pos = [
                       [30, 0, 0],
                       [GlobalVariable.goalkepper_X, 0, 90],
                       [10, -10, 0],
                       [10, 10, 0],
                       [10, 0, 0],
                       [0.0, 0.0, 0.0]]
    else:
        print("race_state = " + str(race_state))

    final_set_pos = [(set_pos[0][0], set_pos[0][1], set_pos[0][2]),
                     (set_pos[1][0], set_pos[1][1], set_pos[1][2]),
                     (set_pos[2][0], set_pos[2][1], set_pos[2][2]),
                     (set_pos[3][0], set_pos[3][1], set_pos[3][2]),
                     (set_pos[4][0], set_pos[4][1], set_pos[4][2]),
                     (set_pos[5][0], set_pos[5][1], set_pos[5][2])]

    last_race_state = race_state   #记录上一次比赛状态
    last_race_state_trigger  = race_state_trigger

    print(final_set_pos)
    return final_set_pos  # 最后一个是球位置（x,y,角）,角其实没用